home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Celestin Apprentice 5
/
Apprentice-Release5.iso
/
Source Code
/
C++
/
Frameworks
/
TransSkel++ 305
/
Source
/
TransSkel++.cp
< prev
Wrap
Text File
|
1996-05-02
|
80KB
|
1,818 lines
/*
** TransSkel++.cp
**
** The TransSkel++ module provides a C++ interface to Paul
** Dubois' TransSkel Application Skeleton. With TransSkel++,
** much of the object-oriented flavor of the TransSkel
** module is massaged into a simple and extendable class
** framework. With not too much fuss, users of TransSkel++
** may create menus, windows, dialogs, and even applications
** in as intuitive a way as C++ will allow.
**
** Compiles under Symantec C/C++ 7.0.4
** Metrowerks C/C++ 8
** Uses TransSkel v3.24
**
** Fred Dushin
** email: fadushin@top.cis.syr.edu
**
** Release 3.04 May 1, 1996 "Dyslexics untie!"
** See release notes for details of changes.
*/
#include <TransSkel++.h>
//----------------------------------------------------------------------/
// internal headers /
//----------------------------------------------------------------------/
//----------------------------------------------------------------------/
// Headers for the mini-list manager /
// Supports: Dynamic creation and destruction of lists /
// via traditional "cons" cells. /
//----------------------------------------------------------------------/
typedef void * elt;
typedef struct consCell{
elt carPtr;
struct consCell *cdrPtr;
} consCell, *list;
#define car(l) ((l)->carPtr)
#define cdr(l) ((l)->cdrPtr)
// A predPtr is a pointer to a predicate (funtion), used as
// a callback for finding items in a list
typedef Boolean (*predPtr)( void * item, void * predParams );
static Boolean hasID( void *item, void *predParams );
static Boolean isThis( void *item, void *predParams );
// list manager function prototypes
static list cons( elt head,elt tail );
static elt findOne( predPtr pred, void * predParams, list l );
static list removeItem( elt item, list l );
static void DestroyCons( consCell * c );
static void DestroyList( list l );
//----------------------------------------------------------------------/
// A menuStruct is merely a menuID and a pointer to /
// the CMenuObj class instance associated with the menuID. /
// TransSkel++ maintains a list of menuStructs as menus /
// are created and destroyed. These structs are themselves /
// dynamically created and deleted. /
//----------------------------------------------------------------------/
typedef struct menuStruct{
short menuID;
CMenuObj *menu;
} menuStruct;
//----------------------------------------------------------------------/
// The menuList is the list of all menuStructs created /
// sApplication is a pointer to the only application /
// sAppleMenu is a pointer to the (ONLY) apple menu /
// /
// appleApplItems is a flag from Paul's SkelApple.c module /
// It is set to true when the user defines an application /
// item in the apple menu; o/w it remains false. /
// DoAppleMenu is lifted directly from SkelApple. It's /
// defined here and called in place of Paul's corresponding function /
// so that Apple menu items are properly handled. /
// DoMenuCommand is a hack of Paul's function by the same name /
//----------------------------------------------------------------------/
static list menuList = nil;
static CApplication *sApplication = nil;
static CMenuObj *sAppleMenu = nil;
static Boolean appleApplItems = false;
static pascal void DoAppleMenu( short menuID, short item );
static Boolean DoMenuCommand( long command );
//----------------------------------------------------------------------/
// The SkelppWindowPropertyID is used to retrieve a structure /
// used internally by TransSkel++. The structure includes a /
// pointer to a CApplObj, ostensibly the CWindow or CDialog /
// class instance associated with the window or dialog. /
// The class instances typically get retrieved in the TransSkel /
// callbacks in order to call the appropriate class methods. /
//----------------------------------------------------------------------/
#define OFFSET 2704
enum{
SkelppWindowPropertyID = skelWPropApplBase + OFFSET
};
typedef struct SkelppWindowProperty{
CApplObj *obj;
// Additional fields for future use (?)
} SkelppWindowProperty;
/*---------------------------------------------------------------------*/
/* TransSkel callbacks */
/* */
/* These "C" functions get passed to TransSkel and get */
/* called at the appropriate events. Except where noted, */
/* most callbacks defined here merely call the methods */
/* of the appropriate class instance, though typically, */
/* these methods will be over-ridden in sub-class definitions. */
/*---------------------------------------------------------------------*/
extern "C"{
// CApplication callbacks
static pascal void _doSuspendResume(Boolean inForeground);
static pascal void _doIdle( void );
static pascal Boolean _doEventHook(EventRecord *evt);
static pascal void _doAE(EventRecord *evt);
// CMenu callbacks
static pascal void _doMenuClobber(MenuHandle menu);
// CAppleMenu callbacks
static pascal void _doAppleSelect( short item );
static pascal void _doAppleClobber(MenuHandle menu);
// CWindow callbacks
static pascal void _doWindowMouseClick(Point where, long when, short modifiers);
static pascal void _doWindowKeyClick(short c, short code, short modifiers);
static pascal void _doWindowUpdate (Boolean resized);
static pascal void _doWindowActivate (Boolean active);
static pascal void _doWindowClose(void);
static pascal void _doWindowClobber(void);
static pascal void _doWindowIdle (void);
// CDialog callbacks
static pascal Boolean _doDialogFilter(DialogPtr dlog, EventRecord *evt, short *item);
static pascal void _doDialogSelect(DialogPtr dlog, short item);
static pascal void _doDialogClose(void);
static pascal void _doDialogClobber(void);
}
//----------------------------------------------------------------------/
// implementation /
//----------------------------------------------------------------------/
//======================================================================/
// The CApplObj Class /
// /
// Base Class: none /
// Methods: • Error(Str255 errorStr, short code); /
// Handle errors in TransSkel++ /
// /
// Description: Every class in TransSkel++ is a subclass /
// of the ApplObj base class. This permits all objects /
// to inherit the error handling facilities defined therein. /
//======================================================================/
//----------------------------------------------------------------------/
// Error protected /
// /
// Default error handling method. Calls fatalAlert if fatal error /
// message passed in error code, then exits program _abnorammly_ /
// /
// PARAMETERS /
// errorStr: a pascal string when gets printed in alert box /
// code: an error code /
// RETURN VALUE /
// none /
//----------------------------------------------------------------------/
void
CApplObj::Error( Str255 errorStr, short code )
{
switch( code ){
case Skelpp_noErr:
break;
case Skelpp_fatalErr:
FatalAlert( errorStr );
ExitToShell();
break;
}
}
//----------------------------------------------------------------------/
// FatalAlert private /
// /
// Put up an internally defined alert after beeping. Also puts up /
// exit button in alert box and message telling about to exit /
// /
// PARAMETERS /
// str: a pascal string when gets printed in alert box /
// RETURN VALUE /
// none /
//----------------------------------------------------------------------/
void
CApplObj::FatalAlert( Str255 str )
{
SysBeep( 10 );
FakeAlert( str, "\p\r\r", "\pPress Exit to quit program\r", nil,
1, 1, 0, "\pExit", nil, nil );
}
//======================================================================/
// The CApplication Class /
// /
// Base Class: CApplObj Class /
// Methods: • Run(void); /
// Run the application /
// • doEventHook(EventRecord *evt); /
// Respect the host's event hook /
// • doSuspendResume(Boolean inForeground); /
// Handle suspend/resume events /
// • doIdle(void); /
// Handle idle events /
// /
// Description: Every program must have exactly one CApplication /
// class (or subclass) instance, which is pointed to by the static /
// pointer sApplication. Typically, a programmer will define /
// a subclass of the CApplication class for his or her purposes, /
// making it a container for all global storage in the program. /
// /
// The CApplication class constructor adds an event hook for /
// inspecting events before being processed by TransSkel. This /
// event hook is necessary for proper handling of menu events, /
// since TransSkel does not have anything for menus like the /
// property list it supports for windows and dialogs. /
//======================================================================/
//----------------------------------------------------------------------/
// CApplication public /
// /
// The CApplication constructor Initializes TransSkel /
// and registers the idle, suspend/resume, and event hook /
// procedures mentioned above. A pointer to the application /
// is initialized to the (sole) instance of this class. /
// This pointer is needed in order for TransSkel++ to call /
// the class's methods. /
// /
// PARAMETERS /
// initParams: initialization parameters passed to SkelInit /
// RETURN VALUE /
// none /
//----------------------------------------------------------------------/
CApplication::CApplication( SkelInitParamsPtr initParams )
{
if ( !sApplication ){
SkelInit( initParams );
// Set up internal callbacks
SkelSetIdle( _doIdle );
SkelSetSuspendResume( _doSuspendResume );
SkelSetEventHook( _doEventHook );
if ( SkelQuery( skelQHasAppleEvents ) ){
SkelSetAEHandler( _doAE );
}
sApplication = this;
}
else{
Error("\pYou may only define one application", Skelpp_fatalErr);
}
}
//----------------------------------------------------------------------/
// ~CApplication public /
// /
// The CApplication destructor. /
// Calls SkelCleanup() and sets the global sApplication to nil /
// (in the unlikely event host defines a new application). /
// /
// PARAMETERS /
// none /
// RETURN VALUE /
// none /
//----------------------------------------------------------------------/
CApplication::~CApplication(void)
{
SkelCleanup();
sApplication = nil;
}
/*---------------------------------------------------------------------*/
/* TransSkel callbacks for CApplication class */
/* */
/* These "C" functions get passed to TransSkel and get */
/* called at the appropriate events. Except where noted, */
/* most callbacks defined here merely call the methods */
/* of the appropriate class instance, though typically, */
/* these methods will be over-ridden in sub-class definitions. */
/*---------------------------------------------------------------------*/
extern "C"{
/*---------------------------------------------------------------------*/
/* _doSuspendResume static */
/* */
/* Call the application's suspend/resume method */
/* */
/* PARAMETERS */
/* as per TransSkel */
/* RETURN VALUE */
/* as per TransSkel */
/*---------------------------------------------------------------------*/
static pascal void
_doSuspendResume( Boolean inForeground )
{
if ( sApplication ){
sApplication->doSuspendResume( inForeground );
}
}
/*---------------------------------------------------------------------*/
/* _doIdle static */
/* */
/* Call the application's idle method */
/* */
/* PARAMETERS */
/* as per TransSkel */
/* RETURN VALUE */
/* as per TransSkel */
/*---------------------------------------------------------------------*/
static pascal void
_doIdle(void)
{
if ( sApplication ){
sApplication->doIdle();
}
}
/*---------------------------------------------------------------------*/
/* _doEventHook static */
/* */
/* Inspect the event before TransSkel has a chance to. */
/* If there was a mouseDown event in the menubar or a */
/* command key equivalent, process the event by */
/* doing a menu(Select|Key) and calling the doSelect */
/* method in the menu class instance in the menuList. */
/* This is necessary because TransSkel provides no way */
/* of informing the callbacks for the menu handlers of */
/* the menu being invoked; nor are there menu property */
/* lists, as there are for windows and dialogs. */
/* */
/* PARAMETERS */
/* as per TransSkel */
/* RETURN VALUE */
/* as per TransSkel */
/*---------------------------------------------------------------------*/
static pascal Boolean
_doEventHook(EventRecord *evt)
{
Boolean result = false;
if ( !sApplication )
return false;
/* First, respect the host's event hook */
if ( sApplication->doEventHook( evt ) ){
return true;
}
/* otherwise, check for menu events */
switch ( evt->what ){
case mouseDown:
GrafPtr evtPort;
short evtPart;
Rect appleRect;
evtPart = FindWindow ( evt->where, &evtPort );
if ( evtPart == inMenuBar ){
/* First call the CApplication's menu hook */
sApplication->doMenuHook();
/* Then handle the menu command */
result = DoMenuCommand( MenuSelect( evt->where ) );
}
break;
case keyDown:
case autoKey:
char evtChar = evt->message & charCodeMask;
if ( (evt->modifiers & cmdKey) && !SkelCmdPeriod ( evt ) ){
sApplication->doMenuHook();
result = DoMenuCommand( MenuKey( evtChar ) );
}
break;
}
return result;
}
/*---------------------------------------------------------------------*/
/* _doAE static */
/* */
/* Call the application's AE method */
/* */
/* PARAMETERS */
/* as per TransSkel */
/* RETURN VALUE */
/* as per TransSkel */
/*---------------------------------------------------------------------*/
static pascal void
_doAE( EventRecord *evt )
{
if ( sApplication ){
sApplication->doAE( evt );
}
}
} /* extern "C" */
//----------------------------------------------------------------------/
// DoMenuCommand static /
// /
// This definition is adapted from the TransSkel static function by the /
// same name. It's needed here in order to handle selection of items /
// in the apple menu properly. /
// /
// PARAMETERS /
// command: encodes menu/item in long /
// RETURN VALUE /
// true if a menu was handles; false o/w /
//----------------------------------------------------------------------/
static Boolean
DoMenuCommand( long command )
{
short menuID, item;
Boolean result = false;
menuStruct * theMenu;
menuID = HiWord( command );
item = LoWord( command );
/* find the menuStruct in menuList which has menuID */
theMenu = (menuStruct *)findOne( hasID, &menuID, menuList );
if ( theMenu ){
/* Treat Apple menu specially (Because of 'DRVR' resources) */
if ( menuID == skelAppleMenuID ){
DoAppleMenu( menuID, item );
}
else{
theMenu->menu->doSelect( item );
}
result = true;
}
HiliteMenu( 0 );
return result;
}
//----------------------------------------------------------------------/
// DoAppleMenu static /
// /
// Paul's DoAppleItem proc, with minor modification /
// This is lifted directly from SkelApple.c. /
// /
// PARAMETERS /
// menuID: menu ID of apple menu (should be 128) /
// item: menu item selected /
// RETURN VALUE /
// true if a menu was handles; false o/w /
//----------------------------------------------------------------------/
static pascal void
DoAppleMenu( short menuID, short item )
{
GrafPtr curPort;
Str255 str;
Handle h;
short i;
MenuHandle menu = GetMHandle(menuID);
/*
* If there are application items, determine if item is one of them.
* Can tell by tracking backward through the items; if the gray line
* separating application items and DA's if not found before top of
* menu is reached, then its an application item, else a DA. This
* strategy requires that there be no "-" items in the items string
* passed to SkelApple().
*/
if ( appleApplItems )
{
for (i = item; i > 0; i--) /* look from current to item 1 */
{
GetItem (menu, i, str);
if (str[0] == 1 && str[1] == '-')
break;
}
if (i == 0) /* reached top without seeing line */
{
_doAppleSelect(item);
return;
}
}
/* either no application items or selection isn't one of them */
GetPort (&curPort);
GetItem(menu, item, str); /* get DA name */
SetResLoad (false);
h = GetNamedResource ('DRVR', str);
SetResLoad (true);
if (h != (Handle) nil)
{
#if skelUnivHeaders
ReserveMem (GetResourceSizeOnDisk (h) + 0x1000);
#else
/* can't use new name for this one in non-universal headers */
ReserveMem (SizeResource (h) + 0x1000);
#endif
(void) OpenDeskAcc (str); /* open it */
}
SetPort (curPort);
}
//----------------------------------------------------------------------/
// hasID static /
// /
// List handler callback /
// /
// PARAMETERS /
// item: current item on list /
// predParams: parameter passed through list handler /
// RETURN VALUE /
// true if item has same id as that passed through predParames; /
// false, o/w /
//----------------------------------------------------------------------/
static Boolean
hasID(void *item, void *predParams)
{
return( ((menuStruct *)item)->menuID == *(short *)predParams );
}
//----------------------------------------------------------------------/
// isThis static /
// /
// List handler callback /
// /
// PARAMETERS /
// item: current item on list /
// predParams: parameter passed through list handler /
// RETURN VALUE /
// true if item is the same as that passed through predParames; /
// false, o/w /
//----------------------------------------------------------------------/
static Boolean
isThis(void *item, void *predParams)
{
return( ((menuStruct *)item)->menu == (CMenuObj *)predParams );
}
//======================================================================/
// The CMenu Class /
// /
// Base Class: CMenuObj Class /
// Methods: • doSelect(short item); /
// Handle item selections in menu /
// /
// Member variables: /
// • MenuHandle menu; (protected) /
// A handle to the QD menu structure /
// /
// Description: The CMenu class is used for standard (anything /
// not an apple) menu handling. Users of TransSkel++ will typically /
// create subclasses of the CMenu class for each menu in the /
// application (e.g., CFileMenu, CEditMenu, etc.) Because TransSkel /
// treates the Apple menu specially, a special CAppleMenu class /
// is defined below. /
//======================================================================/
//----------------------------------------------------------------------/
// CMenu public /
// /
// The CMenu constructor. /
// /
// PARAMETERS /
// menuID: resource id of new menu /
// subMenu: true if is a submenu /
// drawBar: draw the menubar after creation (usually false) /
// RETURN VALUE /
// none /
//----------------------------------------------------------------------/
CMenu::CMenu( short menuID, Boolean subMenu, Boolean drawBar )
{
menuStruct *ms;
// Create the menu
menu = GetMenu( menuID );
if ( !menu ){
Error( "\pCould not allocate memory for menu", Skelpp_fatalErr );
return;
}
// register it with TransSkel
if ( !SkelMenu( menu,
nil, /* item selection handler */
nil, /* disposal function */
subMenu, /* true if hierarchichal */
drawBar ) /* true if draw after alloc'd */
){
Error( "\pCould not register menu with TransSkel",
Skelpp_fatalErr );
DisposeMenu( menu );
return;
}
// Create a menuStruct to hold menuID and pointer to class instance
if ( !(ms = (menuStruct *)NewPtr( sizeof( menuStruct ) )) ){
Error( "\pCould not allocate internal menu list handler",
Skelpp_fatalErr );
DisposeMenu( menu );
return;
}
// intitialize fields and place on menuList
ms->menuID = menuID;
ms->menu = this;
menuList = cons( ms, menuList );
}
//----------------------------------------------------------------------/
// ~CMenu public /
// /
// The CMenu destructor. /
// First get rid of the menuStruct on the menuList, if it exists /
// Then call SkelRmveWindow, which deletes the menu from the /
// menubar, redraws the menubar, and then calls the clobber /
// proc for the menu, which in this case will be _doMenuClobber /
// (which frees space tied up by menu). This is safe, /
// assuming the user has not called SkelRmveMenu or SkelCleanup /
// _before_ deleting the menu instance. /
// /
// PARAMETERS /
// none /
// RETURN VALUE /
// none /
//----------------------------------------------------------------------/
CMenu::~CMenu(void)
{
menuStruct *ms;
ms = (menuStruct *)findOne( isThis, this, menuList );
if ( ms ){
menuList = removeItem( ms , menuList );
DisposePtr( (Ptr)ms );
}
SkelRmveMenu( menu );
DisposeMenu( menu );
}
/*---------------------------------------------------------------------*/
/* TransSkel callbacks for CMenu class */
/* */
/* These "C" functions get passed to TransSkel and get */
/* called at the appropriate events. Except where noted, */
/* most callbacks defined here merely call the methods */
/* of the appropriate class instance, though typically, */
/* these methods will be over-ridden in sub-class definitions. */
/*---------------------------------------------------------------------*/
extern "C"{
/*---------------------------------------------------------------------*/
/* _doMenuClobber static */
/* */
/* For future use */
/* */
/* PARAMETERS */
/* as per TransSkel */
/* RETURN VALUE */
/* as per TransSkel */
/*---------------------------------------------------------------------*/
static pascal void
_doMenuClobber( MenuHandle menu ){}
} /* extern "C" */
//======================================================================/
// The CAppleMenu Class /
// /
// Base Class: CMenuObj Class /
// Methods: • doSelect(short item); /
// Handle item selections in Apple menu /
// /
// Description: The CAppleMenu class is used for managing the /
// apple menu. Because TransSkel treats the apple menu specially, /
// (with SkelApple), a special class constructor is needed. Also, /
// TransSkel provides for no destructors for Apple menus, so /
// the CAppleMenu class has no clobber method. /
//======================================================================/
//----------------------------------------------------------------------/
// CAppleMenu public /
// /
// The CAppleMenu constructor. /
// /
// PARAMETERS /
// items: Pascal String for about menu item(s) /
// RETURN VALUE /
// none /
//----------------------------------------------------------------------/
CAppleMenu::CAppleMenu( const StringPtr items )
{
menuStruct *ms;
/* 024 = apple character */
menu = NewMenu( skelAppleMenuID, (StringPtr) "\p\024" );
if (items != (StringPtr) nil && items[0] > 0)
{
/* application has own items in menu */
appleApplItems = true;
/* add items */
AppendMenu( menu, items );
/* add gray line */
AppendMenu( menu, (StringPtr) "\p(-" );
}
AddResMenu( menu, 'DRVR' ); /* add desk accessories */
(void) SkelMenu ( menu, _doAppleSelect, _doAppleClobber,
false, false );
if ( !sAppleMenu ){
if ( !(ms = (menuStruct *)NewPtr( sizeof( menuStruct ) )) ){
Error( "\pCould not allocate internal menu list handler",
Skelpp_fatalErr );
DisposeMenu( menu );
return;
}
ms->menuID = 128;
ms->menu = this;
menuList = cons( ms, menuList );
sAppleMenu = this;
}
else{
Error( "\pYou may only have one apple menu",
Skelpp_fatalErr );
}
}
//----------------------------------------------------------------------/
// ~CAppleMenu public /
// /
// The CAppleMenu destructor. /
// First get rid of the menuStruct on the menuList, if it exists, /
// and restore globals to their original state (just in case /
// user decides to make a new apple menu on-the-fly). /
// Then call SkelRmveWindow, which deletes the menu from the /
// menubar, redraws the menubar, and then calls the clobber /
// proc for the menu, which in this case will be _doAppleClobber /
// (which frees space tied up by menu) /
// /
// PARAMETERS /
// none /
// RETURN VALUE /
// none /
//----------------------------------------------------------------------/
CAppleMenu::~CAppleMenu( void )
{
menuStruct *ms;
ms = (menuStruct *)findOne( isThis, this, menuList );
if ( ms ){
menuList = removeItem( ms , menuList );
DisposePtr( (Ptr)ms );
}
sAppleMenu = nil; /* restore */
appleApplItems = false; /* globals */
SkelRmveMenu( menu );
}
/*---------------------------------------------------------------------*/
/* TransSkel callbacks for CAppleMenu class */
/* */
/* These "C" functions get passed to TransSkel and get */
/* called at the appropriate events. Except where noted, */
/* most callbacks defined here merely call the methods */
/* of the appropriate class instance, though typically, */
/* these methods will be over-ridden in sub-class definitions. */
/*---------------------------------------------------------------------*/
extern "C"{
/*---------------------------------------------------------------------*/
/* _doAppleSelect static */
/* */
/* Handle selections in apple menu */
/* With the current version, this is completely gratuitous */
/* */
/* PARAMETERS */
/* as per TransSkel */
/* RETURN VALUE */
/* as per TransSkel */
/*---------------------------------------------------------------------*/
static pascal void
_doAppleSelect( short item )
{
sAppleMenu->doSelect(item);
}
/*---------------------------------------------------------------------*/
/* _doAppleClobber static */
/* */
/* Free up dynamically allocated menu, if it exists */
/* */
/* PARAMETERS */
/* as per TransSkel */
/* RETURN VALUE */
/* as per TransSkel */
/*---------------------------------------------------------------------*/
static pascal void
_doAppleClobber( MenuHandle menu )
{
if ( menu )
DisposeMenu( menu );
}
} /* extern "C" */
//======================================================================/
// The CWindow Class /
// /
// Base Class: CApplObj Class /
// Methods: • doMouseClick(Point where, long when, short modifiers);/
// Handle mouse clicks in window /
// • doKeyClick(short c, short code, short modifiers); /
// Handle key clicks in window /
// • doUpdate(Boolean resized); /
// Handle Update events in window /
// • doActivate(Boolean active); /
// Handle Activate events in window /
// • doClose(void); /
// Handle closing window (default method /
// hides window via HideWindow()) /
// • doIdle(void); /
// Handle idle events in window /
// • doShow(void); /
// Display window (Calls Show/SelectWindow()) /
// • GetWindowPtr(void); /
// Returns WindowPtr to QD window struct /
// /
// Member variables: /
// • WindowPtr wind; (protected) /
// A pointer to the QD window structure /
// /
// Description: The CWindow class is the base class for all window /
// objects in TransSkel++. Users will typically create subclasses /
// of the CWindow class (e.g., CDrawWindow, CStatusWindow, etc.) /
// and override any of the above methods and/or create new ones. /
//======================================================================/
//----------------------------------------------------------------------/
// CWindow public /
// /
// The CWindow constructor. /
// /
// PARAMETERS /
// wStorage /
// boundsRect /
// tile /
// visible /
// procID /
// behind as per IM:ToolBox Essentials /
// goAway /
// refCon /
// frontIdle Call idle event proc only if frontmost /
// RETURN VALUE /
// none /
//----------------------------------------------------------------------/
CWindow::CWindow( Ptr wStorage,
Rect *boundsRect,
Str255 title,
Boolean visible,
int procID,
WindowPtr behind,
Boolean goAway,
long refCon,
Boolean frontIdle )
{
SkelppWindowProperty **p;
if ( SkelQuery( skelQHasColorQD ) ){
wind = NewCWindow( wStorage, boundsRect, title, visible,
procID, behind, goAway, refCon );
}
else{
wind = NewWindow( wStorage, boundsRect, title, visible,
procID, behind, goAway, refCon);
}
if ( !wind ){
Error( "\pCould not allocate memory for wind",
Skelpp_fatalErr );
return;
}
if ( !SkelWindow ( wind,
_doWindowMouseClick, /* mouse click handler */
_doWindowKeyClick, /* key click handler */
_doWindowUpdate, /* update event handler */
_doWindowActivate, /* activate event handler */
_doWindowClose, /* close box click handler */
nil, /* disposal function */
_doWindowIdle, /* idle-time handler */
frontIdle ) /* idle only when frontmost */
){
Error( "\pCould not register wind with TransSkel",
Skelpp_fatalErr );
DisposeWindow( wind );
return;
}
// Create a SkelppWindowProperty and place a handle to it on the
// property list of the new window, indexed by SkelppWindowPropertyID
if ( !(p = (SkelppWindowProperty **)
NewHandle( sizeof( SkelppWindowProperty ) )) ){
Error( "\pCould not allocate memory for window property",
Skelpp_fatalErr );
SkelRmveWind( wind );
DisposeWindow( wind );
return;
}
(**p).obj = this;
if ( !SkelAddWindProp( wind, SkelppWindowPropertyID, (long)p ) ){
Error( "\pCould not put Skel++ window property on property list",
Skelpp_fatalErr );
SkelRmveWind( wind );
DisposeWindow( wind );
return;
}
}
//----------------------------------------------------------------------/
// CWindow public /
// /
// The CWindow constructor. /
// /
// PARAMETERS /
// windID /
// wStorage /
// behind as per IM:ToolBox Essentials /
// frontIdle Call idle event proc only if frontmost /
// RETURN VALUE /
// none /
//----------------------------------------------------------------------/
CWindow::CWindow( short windID,
Ptr wStorage,
WindowPtr behind,
Boolean frontIdle )
{
SkelppWindowProperty **p;
if ( SkelQuery( skelQHasColorQD ) ){
wind = GetNewCWindow( windID, wStorage, behind );
}
else{
wind = GetNewCWindow( windID, wStorage, behind );
}
if ( !wind ){
Error( "\pCould not allocate memory for wind",
Skelpp_fatalErr );
return;
}
if ( !SkelWindow ( wind,
_doWindowMouseClick, /* mouse click handler */
_doWindowKeyClick, /* key click handler */
_doWindowUpdate, /* update event handler */
_doWindowActivate, /* activate event handler */
_doWindowClose, /* close box click handler */
nil, /* disposal function */
_doWindowIdle, /* idle-time handler */
frontIdle ) /* idle only when frontmost */
){
Error( "\pCould not register wind with TransSkel",
Skelpp_fatalErr );
DisposeWindow( wind );
return;
}
// Create a SkelppWindowProperty and place a handle to it on the
// property list of the new window, indexed by SkelppWindowPropertyID
if ( !(p = (SkelppWindowProperty **)
NewHandle( sizeof( SkelppWindowProperty ) )) ){
Error( "\pCould not allocate memory for window property",
Skelpp_fatalErr );
SkelRmveWind( wind );
DisposeWindow( wind );
return;
}
(**p).obj = this;
if ( !SkelAddWindProp( wind, SkelppWindowPropertyID, (long)p ) ){
Error( "\pCould not put Skel++ window property on property list",
Skelpp_fatalErr );
SkelRmveWind( wind );
DisposeWindow( wind );
return;
}
}
//----------------------------------------------------------------------/
// ~CWindow public /
// /
// The CWindow destructor. /
// /
// PARAMETERS /
// none /
// RETURN VALUE /
// none /
//----------------------------------------------------------------------/
CWindow::~CWindow( void )
{
SkelppWindowProperty **p;
if ( wind ){
p = (SkelppWindowProperty **)
SkelGetWindPropData( wind, SkelppWindowPropertyID );
SkelRmveWindProp( wind, SkelppWindowPropertyID );
DisposeHandle( (Handle)p );
SkelRmveWind( wind );
DisposeWindow( wind );
}
}
//----------------------------------------------------------------------/
// doShow protected /
// /
// Default doShow method /
// /
// PARAMETERS /
// none /
// RETURN VALUE /
// none /
//----------------------------------------------------------------------/
void
CWindow::doShow( void )
{
ShowWindow( wind );
SelectWindow( wind );
}
//----------------------------------------------------------------------/
// GetCWindow /
// /
// returns a pointer to the class instance associated with wind /
// /
// PARAMETERS /
// wind: a WindowPtr /
// RETURN VALUE /
// pointer to CWindow instance associated with wind, if it /
// exists; nil o/w /
//----------------------------------------------------------------------/
CWindow *
GetCWindow( WindowPtr wind )
{
SkelppWindowProperty **p = nil;
if ( wind ){
p = (SkelppWindowProperty **)
SkelGetWindPropData( wind, SkelppWindowPropertyID );
}
return( p ? (CWindow *)((**p).obj) : nil );
}
/*---------------------------------------------------------------------*/
/* TransSkel callbacks for CWindow class */
/* */
/* These "C" functions get passed to TransSkel and get */
/* called at the appropriate events. Except where noted, */
/* most callbacks defined here merely call the methods */
/* of the appropriate class instance, though typically, */
/* these methods will be over-ridden in sub-class definitions. */
/*---------------------------------------------------------------------*/
extern "C" {
/*---------------------------------------------------------------------*/
/* _doWindowMouseClick static */
/* */
/* Handle mouseclicks in window */
/* Calls corresponding class instance's doMouseClick method. */
/* */
/* PARAMETERS */
/* as per TransSkel */
/* RETURN VALUE */
/* as per TransSkel */
/*---------------------------------------------------------------------*/
static pascal void
_doWindowMouseClick( Point where, long when, short modifiers )
{
WindowPtr wind;
CWindow *w;
GetPort(&wind);
if ( wind && (w = GetCWindow( wind )) ){
w->doMouseClick( where, when, modifiers );
}
}
/*---------------------------------------------------------------------*/
/* _doWindowKeyClick static */
/* */
/* Handle keyclicks in window */
/* Calls corresponding class instance's doKeyClick method. */
/* */
/* PARAMETERS */
/* as per TransSkel */
/* RETURN VALUE */
/* as per TransSkel */
/*---------------------------------------------------------------------*/
static pascal void
_doWindowKeyClick( short c, short code, short modifiers )
{
WindowPtr wind;
CWindow *w;
GetPort(&wind);
if ( w = GetCWindow( wind ) ){
w->doKeyClick( c, code, modifiers );
}
}
/*---------------------------------------------------------------------*/
/* _doWindowUpdate static */
/* */
/* Handle window updates */
/* Calls corresponding class instance's doUpdate method. */
/* */
/* PARAMETERS */
/* as per TransSkel */
/* RETURN VALUE */
/* as per TransSkel */
/*---------------------------------------------------------------------*/
static pascal void
_doWindowUpdate( Boolean resized )
{
WindowPtr wind;
CWindow *w;
GetPort( &wind );
if ( w = GetCWindow( wind ) ){
w->doUpdate( resized );
}
}
/*---------------------------------------------------------------------*/
/* _doWindowActivate static */
/* */
/* Handle window activates */
/* Calls corresponding class instance's doActivate method. */
/* */
/* PARAMETERS */
/* as per TransSkel */
/* RETURN VALUE */
/* as per TransSkel */
/*---------------------------------------------------------------------*/
static pascal void
_doWindowActivate ( Boolean active )
{
WindowPtr wind;
CWindow *w;
GetPort( &wind );
if ( w = GetCWindow( wind ) ){
w->doActivate( active );
}
}
/*---------------------------------------------------------------------*/
/* _doWindowClose static */
/* */
/* Handle closebox selections */
/* Calls corresponding class instance's doClose method. */
/* */
/* PARAMETERS */
/* as per TransSkel */
/* RETURN VALUE */
/* as per TransSkel */
/*---------------------------------------------------------------------*/
static pascal void
_doWindowClose( void )
{
WindowPtr wind;
CWindow *w;
GetPort( &wind );
if ( w = GetCWindow( wind ) ){
w->doClose();
}
}
/*---------------------------------------------------------------------*/
/* _doWindowIdle static */
/* */
/* Handle idle events in window */
/* Calls corresponding class instance's doIdle method. */
/* */
/* PARAMETERS */
/* as per TransSkel */
/* RETURN VALUE */
/* as per TransSkel */
/*---------------------------------------------------------------------*/
static pascal void
_doWindowIdle( void )
{
WindowPtr wind;
CWindow *w;
GetPort( &wind );
if ( w = GetCWindow( wind ) ){
w->doIdle();
}
}
} /* extern "C" */
//======================================================================/
// The CDialog Class /
// /
// Base Class: CApplObj Class /
// Methods: • doFilter(EventRecord *evt, short *item); /
// dialog filter proc /
// • doSelect(short item); /
// Handle item selections in dialog /
// • doClose(void); /
// Handle closing dialog (default method /
// hides window via HideWindow()) /
// • doShow(void); /
// Display dialog (Calls Show/SelectWindow()) /
// • GetDialogPtr(void); /
// Returns DialogPtr to QD dialog struct /
// /
// Member variables: /
// • DialogPtr dlog; (protected) /
// A pointer to the QD dialog structure /
// /
// Description: The CDialog class is the base class for all dialog /
// objects in TransSkel++. Users will typically create subclasses /
// of the CDialog class (e.g., CAboutDialog, CSettingDialog, etc.) /
// and override any of the above methods and/or create new ones. /
//======================================================================/
//----------------------------------------------------------------------/
// CDialog public /
// /
// The CDialog constructor. /
// /
// PARAMETERS /
// dStorage /
// boundsRect /
// title /
// visible /
// procID /
// behind as per IM:ToolBox Essentials /
// goAway /
// refCon /
// items /
// RETURN VALUE /
// none /
//----------------------------------------------------------------------/
CDialog::CDialog( Ptr dStorage,
Rect *boundsRect,
Str255 title,
Boolean visible,
int procID,
DialogPtr behind,
Boolean goAway,
long refCon,
Handle items )
{
SkelppWindowProperty **p;
if ( SkelQuery( skelQHasColorQD ) ){
dlog = NewCDialog( dStorage, boundsRect, title, visible,
procID, behind, goAway, refCon, items );
}
else{
dlog = NewDialog( dStorage, boundsRect, title, visible,
procID, behind, goAway, refCon, items);
}
if ( !dlog ){
Error( "\pCould not allocate memory for dlog",
Skelpp_fatalErr );
return;
}
if ( !SkelDialog ( dlog, /* dialog pointer */
_doDialogFilter, /* filterproc */
_doDialogSelect, /* item handler */
_doDialogClose, /* close handler */
nil ) /* dispose dlog */
){
Error( "\pCould not register dlog with TransSkel",
Skelpp_fatalErr );
DisposeWindow( dlog );
return;
}
// Create a SkelppWindowProperty and place a handle to it on the
// property list of the new window, indexed by SkelppWindowPropertyID
if ( !(p = (SkelppWindowProperty **)
NewHandle( sizeof( SkelppWindowProperty ) )) ){
Error( "\pCould not allocate memory for window property",
Skelpp_fatalErr );
SkelRmveDlog( dlog );
DisposeDialog( dlog );
return;
}
(**p).obj = this;
if ( !SkelAddWindProp( dlog, SkelppWindowPropertyID, (long)p ) ){
Error( "\pCould not put Skel++ window property on property list",
Skelpp_fatalErr );
SkelRmveDlog( dlog );
DisposeDialog( dlog );
return;
}
}
//----------------------------------------------------------------------/
// CDialog public /
// /
// The CDialog constructor. /
// /
// PARAMETERS /
// windID /
// wStorage /
// behind as per IM:ToolBox Essentials /
// RETURN VALUE /
// none /
//----------------------------------------------------------------------/
CDialog::CDialog(short dlogID, Ptr wStorage, WindowPtr behind)
{
SkelppWindowProperty **p;
// No GetNewCDialog ...
dlog = GetNewDialog( dlogID, wStorage, behind );
if ( !dlog ){
Error( "\pCould not allocate memory for dlog",
Skelpp_fatalErr);
return;
}
if ( !SkelDialog ( dlog, /* dialog pointer */
_doDialogFilter, /* filterproc */
_doDialogSelect, /* item handler */
_doDialogClose, /* close handler */
nil ) /* dispose dlog */
){
Error( "\pCould not register dlog with TransSkel",
Skelpp_fatalErr );
DisposeWindow( dlog );
return;
}
// Create a SkelppWindowProperty and place a handle to it on the
// property list of the new window, indexed by SkelppWindowPropertyID
if ( !(p = (SkelppWindowProperty **)
NewHandle( sizeof( SkelppWindowProperty ) )) ){
Error( "\pCould not allocate memory for window property",
Skelpp_fatalErr );
SkelRmveDlog( dlog );
DisposeDialog( dlog );
return;
}
(**p).obj = this;
if ( !SkelAddWindProp( dlog, SkelppWindowPropertyID, (long)p ) ){
Error( "\pCould not put Skel++ window property on property list",
Skelpp_fatalErr );
SkelRmveDlog( dlog );
DisposeDialog( dlog );
return;
}
}
//----------------------------------------------------------------------/
//~ CDialog public /
// /
// The CDialog constructor. /
// Call SkelRmveDlog, which deletes the TransSkel internal /
// dialog handler, and then calls the clobber /
// proc for the dlog, which in this case will be _doDialogClobber /
// (which frees space tied up by dlog). This is safe, /
// assuming the user has not called SkelRmveDlog or SkelCleanup /
// _before_ deleting the dlog instance. /
// /
// PARAMETERS /
// none /
// RETURN VALUE /
// none /
//----------------------------------------------------------------------/
CDialog::~CDialog( void )
{
SkelppWindowProperty **p;
if ( dlog ){
p = (SkelppWindowProperty **)
SkelGetWindPropData( dlog, SkelppWindowPropertyID );
SkelRmveWindProp( dlog, SkelppWindowPropertyID );
DisposeHandle( (Handle)p );
SkelRmveDlog( dlog );
DisposeDialog( dlog );
}
}
//----------------------------------------------------------------------/
// doShow protected /
// /
// Default doShow method /
// /
// PARAMETERS /
// none /
// RETURN VALUE /
// none /
//----------------------------------------------------------------------/
void
CDialog::doShow(void)
{
ShowWindow(dlog);
SelectWindow(dlog);
}
//----------------------------------------------------------------------/
// GetCDialog /
// /
// returns a pointer to the class instance associated with dlog /
// /
// PARAMETERS /
// dlog: a DialogPtr /
// RETURN VALUE /
// pointer to CDialog instance associated with dlog, if it /
// exists; nil o/w /
//----------------------------------------------------------------------/
CDialog *
GetCDialog( DialogPtr dlog )
{
SkelppWindowProperty **p = nil;
if ( dlog ){
p = (SkelppWindowProperty **)
SkelGetWindPropData( dlog, SkelppWindowPropertyID );
}
return( p ? (CDialog *)(**p).obj : nil );
}
/*---------------------------------------------------------------------*/
/* TransSkel callbacks for CDialog class */
/* */
/* These "C" functions get passed to TransSkel and get */
/* called at the appropriate events. Except where noted, */
/* most callbacks defined here merely call the methods */
/* of the appropriate class instance, though typically, */
/* these methods will be over-ridden in sub-class definitions. */
/*---------------------------------------------------------------------*/
extern "C" {
/*---------------------------------------------------------------------*/
/* _doDialogFilter static */
/* */
/* The dialog's filter proc */
/* Calls corresponding class instance's doFilter method. */
/* */
/* PARAMETERS */
/* as per TransSkel */
/* RETURN VALUE */
/* as per TransSkel */
/*---------------------------------------------------------------------*/
static pascal Boolean
_doDialogFilter(DialogPtr dlog, EventRecord *evt, short *item)
{
CDialog *d;
Boolean b = false;
if ( d = GetCDialog( dlog ) ){
b = d->doFilter( evt, item );
}
return b;
}
/*---------------------------------------------------------------------*/
/* _doDialogSelect static */
/* */
/* The dialog's item selection proc */
/* Calls corresponding class instance's doSelect method. */
/* */
/* PARAMETERS */
/* as per TransSkel */
/* RETURN VALUE */
/* as per TransSkel */
/*---------------------------------------------------------------------*/
static pascal void
_doDialogSelect( DialogPtr dlog, short item )
{
CDialog *d;
if ( d = GetCDialog( dlog ) ){
d->doSelect( item );
}
}
/*---------------------------------------------------------------------*/
/* _doDialogClose static */
/* */
/* The dialog's item close proc */
/* Calls corresponding class instance's doClose method. */
/* */
/* PARAMETERS */
/* as per TransSkel */
/* RETURN VALUE */
/* as per TransSkel */
/*---------------------------------------------------------------------*/
static pascal void
_doDialogClose( void )
{
CDialog *d;
DialogPtr dlog;
GetPort( &dlog );
if ( d = GetCDialog( dlog ) ){
d->doClose();
}
}
} /* extern "C" */
//----------------------------------------------------------------------/
// /
// List Handler /
// /
// This mini list handler creates dynamic lists using traditional /
// cons cells which point to (perhaps) dynamically allocated /
// data objects. For the most part, lists are assumed to be /
// flat (no nested lists), and the cdr of last cons cell in the list /
// is assumed to point to nil. OK as long as cons(itemn, nil) is /
// called first. /
// /
// list -->+---+---+ +---+---+ +---+-+ /
// | o | o---->| o | o----> ... --->| o |\| /
// +-|-+---+ +-|-+---+ +-|-+-+ /
// v v v /
// item1 item2 itemn /
// /
// The following functions provide a minimal set of routines /
// for handling the static menuList which keeps track of which /
// menus have been defined in TransSkel++. Based on Fred's /
// List Manager. Supports: /
// • list cons(elt head, elt tail); /
// Returns the cons of head and tail, as a consCell. /
// It is the user's responsibility to destroy cell. /
// • elt findOne(predPtr pred, void * predParams, list l); /
// Find first item in list which satisfies pred(predParams) /
// • list removeItem(elt item, list l); /
// Remove consCell in list which points to item. /
// • void DestroyCons(consCell * c); /
// Deallocate consCell (assuming created via cons) /
// Leaves item pointed to by cons intact. /
// • void DestroyList(list l); /
// Deallocate all consCells in list (assuming created /
// via cons) Leaves items pointed to by cons' intact. /
//----------------------------------------------------------------------/
//----------------------------------------------------------------------/
// cons static /
// /
// returns -->+---+---+ /
// | o | o----> tail /
// +-|-+---+ /
// v /
// head /
// /
// PARAMETERS /
// head /
// tail /
// RETURN VALUE /
// new list with head in position 1 /
//----------------------------------------------------------------------/
static list
cons( elt head, elt tail )
{
list newCell;
if ( !(newCell = (list)NewPtr( sizeof( consCell ) )) ){
return nil;
}
car(newCell) = head;
cdr(newCell) = (consCell *)tail;
return newCell;
}
//----------------------------------------------------------------------/
// findOne static /
// /
// returns a pointer to first element in l statisfying predicate pred; /
// nil if none found. /
// /
// PARAMETERS /
// pred: predicate to apply to elts in list /
// predParams: parameter passed to pred /
// l: list in which to search /
// RETURN VALUE /
// new list with head in position 1 /
//----------------------------------------------------------------------/
static elt
findOne( predPtr pred, void * predParams, list l )
{
Boolean found = false;
/*
* short circuit evaluation
*/
while ( l && !(found = (*pred)( car(l), predParams )) ){
l = cdr(l);
}
return (found ? car(l) : nil);
}
//----------------------------------------------------------------------/
// removeItem static /
// /
// removes item from list (destructive). Returns pointer to the /
// orginal list. /
// /
// PARAMETERS /
// item: item to be removed /
// l: list from which to remove item /
// RETURN VALUE /
// new list with item removed; old list if item not in list /
//----------------------------------------------------------------------/
static list
removeItem( elt item, list l )
{
Boolean found = false;
list prev = nil, origList = l;
/*
* short circuit evaluation
*/
while ( l && !(found = (item == car(l))) ){
prev = l;
l = cdr(l);
}
if ( found ){
/* l is non-nil */
if ( prev ){
if ( cdr(l) ){ /* l is in middle of list */
cdr(prev) = cdr(l);
}
else{ /* l is last item in list */
cdr(prev) = nil;
}
}
else{ /* l is first item in list */
origList = cdr(l);
}
DestroyCons( l );
}
return origList;
}
//----------------------------------------------------------------------/
// DestroyCons static /
// /
// Deallocates memory for consCell c / /
// /
// PARAMETERS /
// c: cons cell to be destroyed /
// RETURN VALUE /
// none /
//----------------------------------------------------------------------/
static void
DestroyCons( consCell * c )
{
if ( c )
DisposePtr( (Ptr)c );
}
//----------------------------------------------------------------------/
// DestroyList static /
// /
// Deallocates memory for each consCell in List / /
// /
// PARAMETERS /
// l: list to be destroyed /
// RETURN VALUE /
// none /
//----------------------------------------------------------------------/
static void
DestroyList( list l )
{
list tmpList;
while ( l ){
tmpList = (list)cdr(l);
DestroyCons( l );
l = tmpList;
}
}